/*!
 * \file ICtaStraCtx.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief CTA策略上下文接口定义
 * 
 * \details 该文件定义了CTA（Commodity Trading Advisor）策略的核心接口。
 *          CTA策略是一种中低频量化交易策略，主要应用于商品期货、股指期货等衍生品交易。
 *          该接口提供了策略运行所需的全部功能，包括：
 *          - 行情数据获取（K线、Tick等）
 *          - 交易操作（开仓、平仓、调仓等）
 *          - 持仓查询和管理
 *          - 策略状态管理
 *          - 日志输出和用户数据存储
 */
#pragma once
#include<string>
#include <stdint.h>
#include <functional>
#include "../Includes/WTSMarcos.h"

NS_WTP_BEGIN
class WTSCommodityInfo;
class WTSTickData;
struct WTSBarStruct;
class WTSKlineSlice;
class WTSTickSlice;

/*!
 * \typedef FuncEnumCtaPosCallBack
 * \brief CTA持仓枚举回调函数类型定义
 * 
 * \details 用于枚举CTA策略持仓时的回调函数类型。
 *          第一个参数为合约代码，第二个参数为持仓数量。
 */
typedef std::function<void(const char*, double)> FuncEnumCtaPosCallBack;

/*!
 * \class ICtaStraCtx
 * \brief CTA策略上下文接口
 * 
 * \details 这是CTA策略的核心接口，定义了策略运行过程中所需的全部功能：
 * 
 * **主要功能模块：**
 * - **生命周期管理**: 初始化、交易时段开始/结束、计算完成等回调
 * - **行情数据获取**: 获取K线数据、Tick数据、最新价格等
 * - **交易操作接口**: 开多仓、开空仓、平多仓、平空仓、调仓等
 * - **持仓管理**: 获取持仓、设置目标持仓、持仓盈亏查询等
 * - **时间和资金**: 获取交易日期、时间、资金数据等
 * - **辅助功能**: 日志输出、用户数据存储等
 * 
 * **使用场景：**
 * - 中低频量化策略开发
 * - 商品期货、股指期货等衍生品交易
 * - 多品种组合策略
 * - 风险管理和资金管理策略
 * 
 * **设计特点：**
 * - 纯虚函数接口，支持多种实现方式
 * - 支持实盘交易和历史回测
 * - 提供丰富的持仓查询接口
 * - 支持用户标签和分层持仓管理
 * 
 * \note 该接口为纯虚接口，具体实现由CtaStraContext类提供
 * \warning 所有交易操作都是异步执行，需要通过持仓查询确认执行结果
 * \see CtaStraContext, CtaStraBaseCtx
 */
class ICtaStraCtx
{
public:
	/*!
	 * \brief 构造函数
	 * \param[in] name 策略名称
	 */
	ICtaStraCtx(const char* name) :_name(name){}
	virtual ~ICtaStraCtx(){}

	/*!
	 * \brief 获取策略名称
	 * \return 策略名称字符串
	 */
	inline const char* name() const{ return _name.c_str(); }

public:
	/*!
	 * \brief 获取策略ID
	 * \return 策略的唯一标识ID
	 */
	virtual uint32_t id() = 0;

	//回调函数
	/*!
	 * \brief 策略初始化回调
	 * 
	 * \details 策略启动时被调用，用于进行策略的初始化工作：
	 *          - 加载策略参数和配置
	 *          - 初始化策略状态变量
	 *          - 订阅需要的行情数据
	 *          - 设置初始持仓目标等
	 * 
	 * \note 该函数在策略生命周期中只会被调用一次
	 * \warning 不要在此函数中进行交易操作，应该在on_calculate中进行
	 */
	virtual void on_init() = 0;
	
	/*!
	 * \brief 交易时段开始回调
	 * \param[in] uTDate 交易日期，格式为YYYYMMDD
	 * 
	 * \details 每个交易时段开始时被调用，可用于：
	 *          - 更新策略状态
	 *          - 重置日内统计变量
	 *          - 进行开盘前的准备工作
	 */
	virtual void on_session_begin(uint32_t uTDate) = 0;
	
	/*!
	 * \brief 交易时段结束回调
	 * \param[in] uTDate 交易日期，格式为YYYYMMDD
	 * 
	 * \details 每个交易时段结束时被调用，可用于：
	 *          - 保存策略状态和统计数据
	 *          - 进行收盘后的清理工作
	 *          - 计算当日盈亏和绩效指标
	 */
	virtual void on_session_end(uint32_t uTDate) = 0;
	
	/*!
	 * \brief Tick数据更新回调
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] newTick 最新的Tick数据
	 * \param[in] bEmitStrategy 是否触发策略计算，默认为true
	 * 
	 * \details 每当有新的Tick数据到达时被调用，可用于：
	 *          - 更新策略的实时价格
	 *          - 进行高频信号计算
	 *          - 监控盘口变化
	 * 
	 * \note 对于CTA策略，通常不需要在此回调中进行交易操作
	 * \warning 该回调调用频率很高，避免进行复杂计算
	 */
	virtual void on_tick(const char* stdCode, WTSTickData* newTick, bool bEmitStrategy = true) = 0;
	
	/*!
	 * \brief K线数据更新回调
	 * \param[in] stdCode 标准化合约代码  
	 * \param[in] period 周期类型（如"m1"表示1分钟）
	 * \param[in] times 周期倍数
	 * \param[in] newBar 最新的K线数据
	 * 
	 * \details 每当K线数据更新时被调用，主要用于：
	 *          - 更新技术指标
	 *          - 触发基于K线的信号计算
	 *          - 监控价格趋势变化
	 * 
	 * \note 这是CTA策略最重要的数据更新回调
	 */
	virtual void on_bar(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar) = 0;
	
	/*!
	 * \brief 定时调度回调
	 * \param[in] curDate 当前日期，格式为YYYYMMDD
	 * \param[in] curTime 当前时间，格式为HHMM
	 * \return 是否继续执行后续调度
	 * 
	 * \details 按照配置的时间间隔定期调用，可用于：
	 *          - 定时检查策略状态
	 *          - 执行定时任务
	 *          - 进行风险控制检查
	 */
	virtual bool on_schedule(uint32_t curDate, uint32_t curTime) = 0;
	
	/*!
	 * \brief 回测结束回调
	 * 
	 * \details 仅在历史回测模式下，回测结束时被调用，可用于：
	 *          - 计算和输出回测统计结果
	 *          - 保存回测报告
	 *          - 进行策略绩效分析
	 * 
	 * \note 该函数只在回测模式下才会被调用
	 */
	virtual void on_bactest_end() {};

	/*!
	 * \brief 策略计算完成回调
	 * \param[in] curDate 当前日期，格式为YYYYMMDD
	 * \param[in] curTime 当前时间，格式为HHMM
	 * 
	 * \details 策略主要计算逻辑完成后被调用，可用于：
	 *          - 执行一些收尾工作
	 *          - 更新策略状态
	 *          - 发送通知或报告
	 * 
	 * \note 该函数在on_calculate执行完成后被调用
	 */
	virtual void on_calculate_done(uint32_t curDate, uint32_t curTime) { };

	/*!
	 * \brief K线闭合回调
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] period 周期类型字符串
	 * \param[in] newBar 新闭合的K线数据
	 * 
	 * \details 当K线周期结束，新K线闭合时被调用，通常用于：
	 *          - 基于完整K线的技术分析
	 *          - 更新基于闭合价的指标
	 *          - 进行周期性的信号计算
	 */
	virtual void on_bar_close(const char* stdCode, const char* period, WTSBarStruct* newBar) = 0;
	
	/*!
	 * \brief 策略主计算函数
	 * \param[in] curDate 当前日期，格式为YYYYMMDD
	 * \param[in] curTime 当前时间，格式为HHMM
	 * 
	 * \details 策略的核心计算逻辑，在此函数中实现：
	 *          - 技术指标计算
	 *          - 交易信号生成
	 *          - 持仓调整决策
	 *          - 风险管理逻辑
	 * 
	 * \note 这是策略最重要的函数，所有交易决策都应在此实现
	 */
	virtual void on_calculate(uint32_t curDate, uint32_t curTime) = 0;
	
	/*!
	 * \brief Tick数据更新后回调
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] newTick 最新的Tick数据
	 * 
	 * \details Tick数据处理完成后的回调，可用于：
	 *          - 获取处理后的Tick数据
	 *          - 进行后续的数据分析
	 *          - 更新相关的衍生数据
	 * 
	 * \note 默认为空实现，策略可根据需要重写
	 */
	virtual void on_tick_updated(const char* stdCode, WTSTickData* newTick){}

	/*!
	 * \brief 枚举所有持仓
	 * \param[in] cb 持仓枚举回调函数
	 * 
	 * \details 遍历策略的所有持仓，对每个持仓调用回调函数：
	 *          - 可用于统计总持仓
	 *          - 进行持仓分析
	 *          - 实现自定义的持仓管理逻辑
	 */
	virtual void enum_position(FuncEnumCtaPosCallBack cb) = 0;

	//交易接口
	/*!
	 * \brief 开多仓
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] qty 开仓数量（手）
	 * \param[in] userTag 用户标签，用于跟踪特定的交易逻辑，默认为空
	 * \param[in] limitprice 限价，为0表示市价，默认为0
	 * \param[in] stopprice 止损价，为0表示不设止损，默认为0
	 * 
	 * \details 开立多头仓位，策略看涨时使用：
	 *          - qty>0: 增加多头仓位
	 *          - userTag: 可用于标识不同的交易策略或信号
	 *          - 支持限价和市价两种方式
	 * 
	 * \note 该操作是异步的，执行结果需要通过持仓查询确认
	 * \warning 要注意仓位限制和风险控制
	 */
	virtual void stra_enter_long(const char* stdCode, double qty, const char* userTag = "", double limitprice = 0.0, double stopprice = 0.0) = 0;
	
	/*!
	 * \brief 开空仓
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] qty 开仓数量（手）
	 * \param[in] userTag 用户标签，默认为空
	 * \param[in] limitprice 限价，为0表示市价，默认为0
	 * \param[in] stopprice 止损价，为0表示不设止损，默认为0
	 * 
	 * \details 开立空头仓位，策略看跌时使用：
	 *          - qty>0: 增加空头仓位
	 *          - 适用于期货等支持做空的品种
	 * 
	 * \note 该操作是异步的，执行结果需要通过持仓查询确认
	 */
	virtual void stra_enter_short(const char* stdCode, double qty, const char* userTag = "", double limitprice = 0.0, double stopprice = 0.0) = 0;
	
	/*!
	 * \brief 平多仓
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] qty 平仓数量（手）
	 * \param[in] userTag 用户标签，默认为空
	 * \param[in] limitprice 限价，为0表示市价，默认为0
	 * \param[in] stopprice 止损价，为0表示不设止损，默认为0
	 * 
	 * \details 平掉多头仓位：
	 *          - qty>0: 减少多头仓位
	 *          - 如果qty大于当前多头持仓，则全部平掉
	 * 
	 * \note 该操作是异步的，执行结果需要通过持仓查询确认
	 */
	virtual void stra_exit_long(const char* stdCode, double qty, const char* userTag = "", double limitprice = 0.0, double stopprice = 0.0) = 0;
	
	/*!
	 * \brief 平空仓
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] qty 平仓数量（手）
	 * \param[in] userTag 用户标签，默认为空
	 * \param[in] limitprice 限价，为0表示市价，默认为0
	 * \param[in] stopprice 止损价，为0表示不设止损，默认为0
	 * 
	 * \details 平掉空头仓位：
	 *          - qty>0: 减少空头仓位
	 *          - 如果qty大于当前空头持仓，则全部平掉
	 * 
	 * \note 该操作是异步的，执行结果需要通过持仓查询确认
	 */
	virtual void stra_exit_short(const char* stdCode, double qty, const char* userTag = "", double limitprice = 0.0, double stopprice = 0.0) = 0;

	/*!
	 * \brief 获取当前持仓
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] bOnlyValid 是否只返回有效持仓，默认为false
	 * \param[in] userTag 用户标签，默认为空
	 * \return 持仓数量，正数表示多头，负数表示空头
	 * 
	 * \details 查询指定合约的当前持仓：
	 *          - userTag为空：获取该合约的总持仓
	 *          - userTag不为空：获取该标签下的持仓明细
	 *          - bOnlyValid=true：只统计有效持仓（主要用于T+1品种）
	 * 
	 * \note 返回值正负表示方向，绝对值表示数量
	 */
	virtual double stra_get_position(const char* stdCode, bool bOnlyValid = false, const char* userTag = "") = 0;
	
	/*!
	 * \brief 设置目标持仓
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] qty 目标持仓数量，正数为多头，负数为空头
	 * \param[in] userTag 用户标签，默认为空
	 * \param[in] limitprice 限价，为0表示市价，默认为0
	 * \param[in] stopprice 止损价，为0表示不设止损，默认为0
	 * 
	 * \details 直接设置目标持仓，系统会自动计算需要的交易操作：
	 *          - 如果目标持仓大于当前持仓，会自动开仓
	 *          - 如果目标持仓小于当前持仓，会自动平仓
	 *          - 支持多空切换
	 * 
	 * \note 这是最常用的持仓调整方式，比手动开平仓更便捷
	 */
	virtual void stra_set_position(const char* stdCode, double qty, const char* userTag = "", double limitprice = 0.0, double stopprice = 0.0) = 0;
	
	/*!
	 * \brief 获取最新价格
	 * \param[in] stdCode 标准化合约代码
	 * \return 最新价格，如果没有数据则返回0
	 * 
	 * \details 获取指定合约的最新成交价：
	 *          - 实盘时返回最新的Tick价格
	 *          - 回测时返回当前Bar的收盘价
	 */
	virtual double stra_get_price(const char* stdCode) = 0;

	/*!
	 * \brief 获取交易日期
	 * \return 当前交易日期，格式为YYYYMMDD
	 */
	virtual uint32_t stra_get_tdate() = 0;
	
	/*!
	 * \brief 获取当前日期
	 * \return 当前日期，格式为YYYYMMDD
	 */
	virtual uint32_t stra_get_date() = 0;
	
	/*!
	 * \brief 获取当前时间
	 * \return 当前时间，格式为HHMM
	 */
	virtual uint32_t stra_get_time() = 0;

	/*!
	 * \brief 获取资金数据
	 * \param[in] flag 标志位，0-动态权益，1-总资金
	 * \return 资金数额
	 * 
	 * \details 获取策略的资金信息：
	 *          - flag=0: 动态权益（包含浮动盈亏）
	 *          - flag=1: 总资金
	 */
	virtual double stra_get_fund_data(int flag = 0) = 0;

	/*!
	 * \brief 获取首次开仓时间
	 * \param[in] stdCode 标准化合约代码
	 * \return 首次开仓的时间戳
	 */
	virtual uint64_t stra_get_first_entertime(const char* stdCode) = 0;
	
	/*!
	 * \brief 获取最后开仓时间
	 * \param[in] stdCode 标准化合约代码
	 * \return 最后开仓的时间戳
	 */
	virtual uint64_t stra_get_last_entertime(const char* stdCode) = 0;
	
	/*!
	 * \brief 获取最后平仓时间
	 * \param[in] stdCode 标准化合约代码
	 * \return 最后平仓的时间戳
	 */
	virtual uint64_t stra_get_last_exittime(const char* stdCode) = 0;
	
	/*!
	 * \brief 获取最后开仓价格
	 * \param[in] stdCode 标准化合约代码
	 * \return 最后开仓的平均价格
	 */
	virtual double stra_get_last_enterprice(const char* stdCode) = 0;
	
	/*!
	 * \brief 获取持仓均价
	 * \param[in] stdCode 标准化合约代码
	 * \return 当前持仓的平均开仓价格
	 */
	virtual double stra_get_position_avgpx(const char* stdCode) = 0;
	
	/*!
	 * \brief 获取持仓盈亏
	 * \param[in] stdCode 标准化合约代码
	 * \return 当前持仓的浮动盈亏
	 */
	virtual double stra_get_position_profit(const char* stdCode) = 0;

	/*!
	 * \brief 获取指定标签的开仓时间
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] userTag 用户标签
	 * \return 该标签下的开仓时间戳
	 */
	virtual uint64_t stra_get_detail_entertime(const char* stdCode, const char* userTag) = 0;
	
	/*!
	 * \brief 获取指定标签的开仓成本
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] userTag 用户标签
	 * \return 该标签下的开仓成本价格
	 */
	virtual double stra_get_detail_cost(const char* stdCode, const char* userTag) = 0;
	
	/*!
	 * \brief 获取指定标签的盈亏
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] userTag 用户标签
	 * \param[in] flag 标志位，0-浮动盈亏，1-最大浮动盈亏，-1-最大浮动亏损
	 * \return 该标签下的盈亏金额
	 */
	virtual double stra_get_detail_profit(const char* stdCode, const char* userTag, int flag = 0) = 0;

	/*!
	 * \brief 获取品种信息
	 * \param[in] stdCode 标准化合约代码
	 * \return 品种信息对象指针
	 */
	virtual WTSCommodityInfo* stra_get_comminfo(const char* stdCode) = 0;
	
	/*!
	 * \brief 获取K线数据
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] period 周期字符串，如"m1"、"m5"、"d1"等
	 * \param[in] count 获取的K线根数
	 * \param[in] isMain 是否主力合约，默认为false
	 * \return K线数据切片对象指针
	 * 
	 * \details 获取历史K线数据用于技术分析：
	 *          - period支持分钟线、小时线、日线等
	 *          - count为0表示获取全部数据
	 *          - isMain=true时获取主力合约连续数据
	 */
	virtual WTSKlineSlice*	stra_get_bars(const char* stdCode, const char* period, uint32_t count, bool isMain = false) = 0;
	
	/*!
	 * \brief 获取Tick数据
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] count 获取的Tick数量
	 * \return Tick数据切片对象指针
	 */
	virtual WTSTickSlice*	stra_get_ticks(const char* stdCode, uint32_t count) = 0;
	
	/*!
	 * \brief 获取最新Tick数据
	 * \param[in] stdCode 标准化合约代码
	 * \return 最新的Tick数据对象指针
	 */
	virtual WTSTickData*	stra_get_last_tick(const char* stdCode) = 0;

	/*!
	 * \brief 订阅Tick数据
	 * \param[in] stdCode 标准化合约代码
	 * 
	 * \details 订阅指定合约的Tick数据推送：
	 *          - 订阅后会收到该合约的实时Tick数据
	 *          - 用于需要高频数据的策略
	 */
	virtual void stra_sub_ticks(const char* stdCode) = 0;

	/*!
	 * \brief 输出信息日志
	 * \param[in] message 日志信息
	 */
	virtual void stra_log_info(const char* message) = 0;
	
	/*!
	 * \brief 输出调试日志
	 * \param[in] message 日志信息
	 */
	virtual void stra_log_debug(const char* message) = 0;
	
	/*!
	 * \brief 输出错误日志
	 * \param[in] message 日志信息
	 */
	virtual void stra_log_error(const char* message) = 0;

	/*!
	 * \brief 保存用户数据
	 * \param[in] key 数据键名
	 * \param[in] val 数据值
	 * 
	 * \details 保存策略的自定义数据，用于：
	 *          - 保存策略状态
	 *          - 存储计算结果
	 *          - 记录用户参数
	 * 
	 * \note 数据会持久化存储，重启后仍然有效
	 */
	virtual void stra_save_user_data(const char* key, const char* val){}

	/*!
	 * \brief 加载用户数据
	 * \param[in] key 数据键名
	 * \param[in] defVal 默认值，如果没有找到数据则返回该值
	 * \return 用户数据字符串
	 */
	virtual const char* stra_load_user_data(const char* key, const char* defVal = "") { return defVal; }

protected:
	std::string _name;	///< 策略名称
};

NS_WTP_END